#include "DataRingConsumeThread.hpp"
#include <stdio.h>
//#include <cstdlib>
#include <stdlib.h>
#include "commom.h"
// #include <iostream>
//#include <memory.h>


DataRingConsumeThread::DataRingConsumeThread(TcpSocketDataInfo *pTcpSocketDataInfo): pTcpSocketDataInfo(pTcpSocketDataInfo),errorCount(-1) {
}

DataRingConsumeThread::~DataRingConsumeThread() {
	
	}
void DataRingConsumeThread::printBuffer() {

}
void DataRingConsumeThread::run() 
{
    unsigned char end_cmp[16]  = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};

	char *buffer;
	char *pCurrent;
	char *pStart;
	char *pEnd;
	char *pEventLength;
    char *pMidData;
	bool isHeadFound = false;
	int _0x55Count = 0;
	int _0xaaCount = 0;
	int _eventLengthCount = 0;
	bool isEventLengthFound = false;
	bool isEndFound = false;
	int recvIndex = 0;
	uint64_t lastPulseID = 0;
    typedef enum RingSM{
        RingSM_None,
        RingSM_Head,
        RingSM_Length,
        RingSM_Data,
        RingSM_End,
    } RingSM;
    uint64_t expect_nByte = 1;
    bool dataIsNotEnough = false;
    buffer = (char *)malloc(ByteRingSize);
    pCurrent = pStart = buffer;
    RingSM mRingSM = RingSM_Head;
	while(1)
	{
#if 1
        epicsEventWait(pTcpSocketDataInfo->consumerEvent);
        
        while (!dataIsNotEnough) {
            epicsMutexLock(pTcpSocketDataInfo->mutex);
            if (epicsRingBytesUsedBytes(pTcpSocketDataInfo->ring) > expect_nByte) {
                switch (mRingSM) {
                    case RingSM_Head:{
//                        printf(">>>>>                  RingSM_Head          \n");
                        if(epicsRingBytesGet(pTcpSocketDataInfo->ring,  pCurrent, expect_nByte) == expect_nByte){
                            if (*pCurrent == 0x55)
                            {
                                _0x55Count++;
                                pCurrent++;
                                if (_0x55Count == 16)
                                {
                                    mRingSM = RingSM_Length;
                                    expect_nByte = 4;
                                    isHeadFound = true;
                                    pEventLength = pCurrent;
                                    _0x55Count = 0;
//                                    printf("##  RingSM_Head success   \n");
                                    
                                } 
                            } else {
                                _0x55Count = 0;
                                pCurrent = pStart;
                            }
                        }
                        break;
                    }
                    case RingSM_Length:{
//                        printf(">>>>>                  RingSM_Length          \n");
                        if(epicsRingBytesGet(pTcpSocketDataInfo->ring,  pCurrent, expect_nByte) == expect_nByte){
                            pCurrent += expect_nByte;
                            _eventLengthCount = *((uint32_t *)pEventLength);
                            pMidData = pCurrent;
                            mRingSM = RingSM_Data;
                            expect_nByte = _eventLengthCount * sizeof(EventRawdata) + 60;
//                            printf("##  RingSM_Length success  _eventLengthCount = [%3d] expect_nByte = [%3d]\n", _eventLengthCount, expect_nByte);
                        }
                        break;
                    }
                    case RingSM_Data:{
//                        printf(">>>>>                  RingSM_Data          \n");
                        if(epicsRingBytesGet(pTcpSocketDataInfo->ring,  pCurrent, expect_nByte) == expect_nByte){
                            pCurrent +=expect_nByte;
                            expect_nByte = 16;
                            mRingSM = RingSM_End;
//                            printf("##  RingSM_Data success   \n");
                        }
                        break;
                    }
                    case RingSM_End:{
//                        printf(">>>>>                  RingSM_End          \n");
                        if(epicsRingBytesGet(pTcpSocketDataInfo->ring,  pCurrent, expect_nByte) == expect_nByte){
                            if (memcmp(pCurrent, end_cmp, 16) == 0) {
                                pCurrent +=expect_nByte;
                                pEnd = pCurrent;
                                
                                PulseDataRecieve *pPulseDataRecieve = new PulseDataRecieve((char *)pStart, pEnd - pStart);
                                //pPulseDataRecieve->print();
                                pulseCount++;
//                                printf("##  RingSM_Data success   pulseCount = [%5d] pulseID = [%5d]\n", pulseCount, pPulseDataRecieve->getPulseDataID());
                                PulseData * pPulseData= pPulseDataRecieve->getPulseDataPointer();
                                uint64_t curPulseID = pPulseData->ID;
                                if ((curPulseID - lastPulseID) > 1)
                                {
                                    errorCount++;
                                }
                                lastPulseID = curPulseID;
                                uint32_t eventCount = pPulseData->eventCount;
                                printf(">>> pulseCount = %d curPulseID = %ld, eventCount = %d, errorCount = %d\n", pulseCount, curPulseID,eventCount, errorCount);
                                pTcpSocketDataInfo->pointerRing->push(pPulseDataRecieve);
//                                delete pPulseDataRecieve;
                            }
                            pCurrent = pStart;
                            expect_nByte = 1;
                            mRingSM = RingSM_Head;
                        }
                    }
                    default:
                        break;
                }
            } else {
                dataIsNotEnough = true;
            }
            epicsMutexUnlock(pTcpSocketDataInfo->mutex);
        }
        dataIsNotEnough = false;
        
#else
		if (epicsRingBytesUsedBytes(pTcpSocketDataInfo->ring) > 0)
		{
			epicsMutexLock(pTcpSocketDataInfo->mutex);
			if(epicsRingBytesGet(pTcpSocketDataInfo->ring,  pCurrent, 1) > 0) 
			{	
				// int nUsed = epicsRingBytesUsedBytes(pTcpSocketDataInfo->ring);
				//printf("recv[%d] = %#x\n", pCurrent - pStart, *((unsigned char *)pCurrent));
				// printf("\npTcpSocketDataInfo->ring is [%d]  nUsed is %ld\n", pTcpSocketDataInfo->ring, nUsed);
				if (!isHeadFound)
				{
					if (*pCurrent == 0x55)
					{
						_0x55Count++;
						pCurrent++;
						if (_0x55Count == 16)
						{
							isHeadFound = true;
							pEventLength = pCurrent;
							_0x55Count = 0;
							//printf("isHeadFound is true\n");
						} 
					} else {
						_0x55Count = 0;
						pCurrent = pStart;
					}
				} else { // head is found
					if (!isEndFound)
						{
							if (*(unsigned char *)pCurrent == 0xaa)
							{
								//printf("a 0xaa is at [%d] pulseCount = %d\n",(pCurrent - pStart),  (_0xaaCount+1));
								_0xaaCount++;
								pCurrent++;
								//printf("a 0xaa is found pulseCount = %d\n", _0xaaCount);
								if (_0xaaCount == 16)
								{
									//isEndFound = true;
									isHeadFound = false;
									pEnd = pCurrent;
									pCurrent = pStart;
									_0x55Count = 0;
									_0xaaCount = 0;
									pulseCount++;
									
									PulseDataRecieve *pPulseDataRecieve = new PulseDataRecieve((char *)pStart, pEnd - pStart);
									//pPulseDataRecieve->print();

									pTcpSocketDataInfo->pointerRing->push(pPulseDataRecieve);
									PulseData * pPulseData= pPulseDataRecieve->getPulseDataPointer();
									uint64_t curPulseID = pPulseData->ID;
									if ((curPulseID - lastPulseID) > 1)
									{
										errorCount++;
									}
									lastPulseID = curPulseID;
									uint32_t eventCount = pPulseData->eventCount;
									printf("a package is found pulseCount = %d curPulseID = %ld, eventCount = %d, errorCount = %d\n", pulseCount, curPulseID,eventCount, errorCount);
								} 
							} else {
								_0xaaCount = 0;
								pCurrent++;
							}
						}

				}

			}	
			epicsMutexUnlock(pTcpSocketDataInfo->mutex);
		}
#endif
	}
    free(buffer);

}

